@Transactional | 您所在的位置:网站首页 › spring中Transactional注解的作用使用场景举例 › @Transactional |
@Transactional介绍
一、@Transactional注解可以作用于哪些地方?
作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效
二、@Transactional失效场景
1、@Transactional 应用在非 public 修饰的方法上 之所以会失效是因为在Spring AOP 代理时,如上图所示 TransactionInterceptor (事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource的 computeTransactionAttribute方法,获取Transactional 注解的事务配置信息。 2、@Transactional 注解属性 propagation 设置错误 这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。 TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。 3、@Transactional 注解属性 rollbackFor 设置错误 rollbackFor 可以指定能够触发事务回滚的异常类型。**Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;**其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。 4、同一个类中方法调用,导致@Transactional失效 比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。 原因:因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。 5、异常被你的 catch“吃了”导致@Transactional失效 spring的事务是在调用业务方法之前开始的,业务方法执行完毕之后才执行commit or rollback,事务是否执行取决于是否抛出runtime异常。如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。 6、数据库引擎不支持事务 这种情况出现的概率并不高,事务能否生效数据库引擎是否支持事务是关键。常用的MySQL数据库默认使用支持事务的innodb引擎。一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了。 |
CopyRight 2018-2019 实验室设备网 版权所有 |